/******************************************************************************
Tinapoc Project - The Java Reverse Engineering Toolkit
Copyright (C) 2005  Daniel Reynaud-Plantey

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.
******************************************************************************/

package tina.classparsing;

import tina.utils.StringNormalizer;

public class TinaConstantPoolEntry<E> {
    public static final int CONSTANT_Utf8 = 1,
                            CONSTANT_Integer = 3,
                            CONSTANT_Float = 4,
                            CONSTANT_Long = 5,
                            CONSTANT_Double = 6,
                            CONSTANT_Class = 7,
                            CONSTANT_String = 8,
                            CONSTANT_Fieldref = 9,
                            CONSTANT_Methodref = 10,
                            CONSTANT_InterfaceMethodref = 11,
                            CONSTANT_NameAndType = 12;
    private int type;
    private E value1, value2;
    private TinaConstantPool cp;

    public TinaConstantPoolEntry(int type, E value1, TinaConstantPool cp) {
        this(type, value1, null, cp);
    }

    public TinaConstantPoolEntry(int type, E value1, E value2) {
        this(type, value1, value2, null);
    }

// if the entry has a cp associated, it "knows" its neighbours
    public TinaConstantPoolEntry(int type, E value1, E value2, 
                                   TinaConstantPool cp) {
        if(type==1 || (type>=3 && type <= 12)) {
            this.type = type;
            this.value1 = value1;
            this.value2 = value2;
            this.cp = cp;
        }
        else throw new IllegalArgumentException("UNEXPECTED ERROR: unknown constant pool tag : "+type);
    }

    public int getType() {
        return type;
    } 

    public E getFirstValue() {
        return value1;
    }


    public E getSecondValue() {
        return value2;
    }

    public String toString() {
        switch(type) {
            case CONSTANT_Utf8 :               return "CONSTANT_Utf8 \""
                +StringNormalizer.removeSpecialCharacters((String)value1)+"\"";
            case CONSTANT_Integer :            return "CONSTANT_Integer "+value1;
            case CONSTANT_Float :              return "CONSTANT_Float "+value1;
            case CONSTANT_Long :               return "CONSTANT_Long "+value1;
            case CONSTANT_Double :             return "CONSTANT_Double "+value1;
            case CONSTANT_Class :              return "CONSTANT_Class "+value1;
            case CONSTANT_String :             return "CONSTANT_String "+value1;
            case CONSTANT_Fieldref :           return "CONSTANT_Fieldref "+value1+", "+value2;
            case CONSTANT_Methodref :          return "CONSTANT_Methodref "+value1+", "+value2;
            case CONSTANT_InterfaceMethodref : return "CONSTANT_InterfaceMethodref "+value1+", "+value2;
            case CONSTANT_NameAndType :        return "CONSTANT_NameAndType "+value1+", "+value2;
        }
        return "THIS SHOULD NEVER BE RETURNED";
    }



    public String smartDisplay() throws TinaConstantPoolException {
        if(cp!=null) {
            switch(type) {
                case CONSTANT_Utf8 :
                    return StringNormalizer.removeSpecialCharacters((String)value1);

                case CONSTANT_Integer :
                case CONSTANT_Float :
                case CONSTANT_Long :
                case CONSTANT_Double :
                    return value1.toString();

                case CONSTANT_Class :
                    return cp.elementAt((Integer)value1).smartDisplay();

                case CONSTANT_String :
                    String str = cp.elementAt((Integer)value1).smartDisplay();
                    return "\""+str+"\"";


                case CONSTANT_Fieldref :
                case CONSTANT_Methodref :
                case CONSTANT_InterfaceMethodref :
                    return cp.elementAt((Integer)value1).smartDisplay()
                               +"/"+cp.elementAt((Integer)value2).smartDisplay();

                case CONSTANT_NameAndType :
                    return cp.elementAt((Integer)value1).smartDisplay()
                               +" "+cp.elementAt((Integer)value2).smartDisplay();
            }
        } else throw new TinaConstantPoolException("null constant pool");
        return "THIS SHOULD NEVER BE RETURNED";
    }
}